﻿using baselib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AutoUpdateClient
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            LogHelper.WriteDebug("MainWindow");


            //先检查是否需要升级，不需要则退出程序
            if (!CheckAutoUpdate(out needUpdateFiles))
            {
                LogHelper.WriteInfo("升级检查完毕，不需要升级，程序将退出");

                App.Current.Shutdown();
                return;
            }



            lbDownLoadDirectory.Text = DownLoadDirectory;
            //
            needDwonLoadSize = needUpdateFiles.Sum(a => { return a.FileSize; });
            this.Title = UniqueName + "自动更新客户端";
            if((App.Current as App).StartExeName!=null)
            {
                lbexe.Content = (App.Current as App).StartExeName;
                StartExeName= (App.Current as App).StartExeName;
            }


            if (AutoUpdateNoAttention.ToUpper()=="YES")
            {
                //强制升级，不提示
                lbattention.Content = "正在升级更新程序，请耐心等待";
                updateBtn.IsEnabled = false;
                Task.Run(() => {
                    AutoUpdate(needUpdateFiles);

                });

            }

        }



        const string UpdateConfigFile = "UpdateConfigFile.json";

        string ConfigFilePath
        {
            get
            {
                return DownLoadDirectory + "\\" + UpdateConfigFile;
            }
        }
        string UniqueName = ConfigurationManager.AppSettings["ServerUniqueName"];
        string ServerUrl = ConfigurationManager.AppSettings["UpdateServer"];
        string StartExeName = ConfigurationManager.AppSettings["StartExeName"];
        string DownLoadDir = ConfigurationManager.AppSettings["DownLoadDirectory"];
        string AutoUpdateNoAttention= ConfigurationManager.AppSettings["AutoUpdateNoAttention"];

        /// <summary>
        /// 获取当自身所在目录
        /// </summary>
        /// <returns></returns>
        private string GetCurrDir()
        {
            string basedir = System.AppDomain.CurrentDomain.BaseDirectory;
            if (basedir.EndsWith("\\"))
                basedir = basedir.TrimEnd('\\');

            return basedir;
        }
        string DownLoadDirectory
        {

            get
            {
                if (!Directory.Exists(DownLoadDir))
                {
                    return  Directory.GetParent(GetCurrDir()).FullName;
                }
                DirectoryInfo dir = new DirectoryInfo(DownLoadDir);

                return dir.FullName;
            }
        }

        int needDwonLoadSize = 0;
        int currDwonLoadSize = 0;


        private TotalFileVersion tv;
        private TotalFileVersion tvlocal;
        private List<FileUnit> needUpdateFiles;

        private bool CheckAutoUpdate(out List<FileUnit> needUpdateFiles)
        {
            needUpdateFiles = new List<FileUnit>();
            if (!DownLoadUpdateConfig(ServerUrl, UniqueName))
                return false;
            if (tv == null)
                return false;

            //不存在更新配置文件，则需全部升级
            if (!File.Exists(ConfigFilePath))
            {
                foreach (var dfile in tv.FileUnits)
                {
                    needUpdateFiles.Add(dfile);
                }
                return true;
            }
            else
            {
                using (FileStream totalFileVersionFile = new FileStream(ConfigFilePath, FileMode.Open))
                {
                    using (StreamReader rd = new StreamReader(totalFileVersionFile))
                    {
                        string json = rd.ReadToEnd();
                         tvlocal = Newtonsoft.Json.JsonConvert.DeserializeObject<TotalFileVersion>(json);
                        if (tv.TotalVersion != tvlocal.TotalVersion)
                        {
                            foreach (var dfile in tv.FileUnits)
                            {
                                var filelocal = tvlocal.FileUnits.Find(a => { return a.FileRelativePath == dfile.FileRelativePath; });
                                if (filelocal == null || dfile.Version != filelocal.Version)
                                {
                                    needUpdateFiles.Add(dfile);
                                }
                            }

                            return true;
                        }
                    }

                }
            }
            return false;
        }

        public void UpdateDownloadPersent(int DwonLoadSize)
        {
            Dispatcher.Invoke(()=> {
                currDwonLoadSize += DwonLoadSize;
                downPercent.Value = ((double)currDwonLoadSize / (double)needDwonLoadSize)*100;
            });

        }

        private void AutoUpdate(List<FileUnit> needUpdateFiles)
        {
            //如果有进程，则先关闭进程
            ShutdownMainProgram();



            string downloadUrl = ServerUrl + "/file/DownLoad";
            foreach (var downfile in needUpdateFiles)
            {
                Dispatcher.Invoke(() =>
                {
                    currDownloadFile.Content = downfile.FileRelativePath;
                });
                WebapiHelp.DownLoadFile(downloadUrl, UniqueName, downfile.FileRelativePath, DownLoadDirectory, UpdateDownloadPersent);
                //下载完成后，修改文件的最后修改时间
                string downfilepath = DownLoadDirectory + "\\" + downfile.FileRelativePath;

                FileInfo dfileinfo = new FileInfo(downfilepath);
                dfileinfo.LastAccessTime = downfile.LastUpdateTime;
                dfileinfo.CreationTime = downfile.LastUpdateTime;
                dfileinfo.LastWriteTime = downfile.LastUpdateTime;
            }
            //更新UpdateConfigFile.json
            WebapiHelp.DownLoadFile(downloadUrl, UniqueName, UpdateConfigFile, DownLoadDirectory);


            //关闭自己，启动外部程序
            Dispatcher.Invoke(() =>
            {
                StartMainProgram();

                this.Close();
            });


        }
        /// <summary>
        /// 下载服务器对应UniqueName的UpdateConfigFile.json的内容，
        /// </summary>
        /// <param name="url"></param>
        /// <param name="UniqueName"></param>
        public  bool DownLoadUpdateConfig(string url, string UniqueName)
        {
            url = $"{url}/file/getversion/{UniqueName}";

            Encoding encoding = Encoding.UTF8;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "Get";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(responseStream);
                    var json = reader.ReadToEnd();

                    try
                    {
                        tv = Newtonsoft.Json.JsonConvert.DeserializeObject<TotalFileVersion>(json);

                        return true;

                    }
                    catch (Exception)
                    {

                        MessageBox.Show("下载UpdateConfigFile.json信息失败");
                        return false;
                    }

                }
            }
            return false;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

            lbattention.Content = "正在升级更新程序，请耐心等待";
            updateBtn.IsEnabled = false;
            Task.Run(()=> {
                AutoUpdate(needUpdateFiles);

            });

        }

        private void  StartMainProgram()
        {
            string callBackPath = DownLoadDirectory + "\\" + StartExeName; //
            if (File.Exists(callBackPath))
            {
                Directory.SetCurrentDirectory(DownLoadDirectory);
                System.Diagnostics.Process myProcess = System.Diagnostics.Process.Start(callBackPath, (App.Current as App).Param);
            }
        }

        private void ShutdownMainProgram()
        {
            string processName = StartExeName.Substring(0, StartExeName.Length - 4);

            foreach (Process p in Process.GetProcesses())//GetProcessesByName(strProcessesByName))
            {
                if (p.ProcessName.ToUpper().Contains(processName.ToUpper()))
                {
                    try
                    {
                        LogHelper.WriteInfo($"ShutdownMainProgram {processName}");
                        p.Kill();
                        p.WaitForExit(); // possibly with a timeout
                    }
                    catch (Win32Exception e)
                    {
                        MessageBox.Show(e.Message.ToString());   // process was terminating or can't be terminated - deal with it
                    }
                    catch (InvalidOperationException e)
                    {
                        MessageBox.Show(e.Message.ToString()); // process has already exited - might be able to let this one go
                    }
                }
            }
            
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
    }
}
